package beer.coder.walawala.plugin.demo;

import beer.coder.walawala.common.exception.UIException;
import beer.coder.walawala.common.gui.Toast;
import beer.coder.walawala.common.plugin.IPlugin;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TextArea;
import javafx.scene.image.Image;
import javafx.scene.input.Clipboard;
import javafx.scene.input.ClipboardContent;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Priority;
import javafx.stage.Stage;
import javafx.stage.StageStyle;

/**
 * TODO
 *
 * @author amath0312
 * @version 1.0
 * @date 2020-04-18 23:22
 */
public class DigestCalculatorPlugin implements IPlugin {

  Stage win;

  TextArea txtOrigin;
  TextArea txtValB64;
  TextArea txtValHex;

  @Override
  public void load(Stage main) throws UIException {
    win = new Stage(StageStyle.UNIFIED);
    win.initOwner(null);
    win.setTitle(getName());
    win.setResizable(false);

    GridPane grid = new GridPane();
    grid.setAlignment(Pos.CENTER);
    grid.setPadding(new Insets(5));

    grid.setHgap(10);
    grid.setVgap(10);

    ColumnConstraints column1 = new ColumnConstraints(50, 100, 100);
    ColumnConstraints column2 = new ColumnConstraints(50, 200, 500);
    ColumnConstraints column3 = new ColumnConstraints(50, 80, 100);
    column2.setHgrow(Priority.ALWAYS);
    grid.getColumnConstraints().addAll(column1, column2, column3);

    Label lbOrigin = new Label("原数据");
    txtOrigin = new TextArea();
    txtOrigin.setWrapText(true);
    txtOrigin.setPrefRowCount(1);

    GridPane.setHalignment(lbOrigin, HPos.LEFT);
    grid.add(lbOrigin, 0, 0);

    GridPane.setHalignment(txtOrigin, HPos.LEFT);
    grid.add(txtOrigin, 1, 0);

    Label lbValB64 = new Label("计算结果(BASE64)");
    txtValB64 = new TextArea();
    txtValB64.setWrapText(true);
    txtValB64.setPrefRowCount(1);
    txtValB64.setEditable(false);

    Button btCopyValB64 = new Button("复制");
    btCopyValB64.setOnAction((e) -> {
      ClipboardContent content = new ClipboardContent();
      content.putString(txtValB64.getText());
      Clipboard.getSystemClipboard().setContent(content);
      Toast.make("已复制").show(3000, win);
    });

    GridPane.setHalignment(lbValB64, HPos.LEFT);
    grid.add(lbValB64, 0, 1);

    GridPane.setHalignment(txtValB64, HPos.LEFT);
    grid.add(txtValB64, 1, 1);

    GridPane.setHalignment(btCopyValB64, HPos.LEFT);
    grid.add(btCopyValB64, 2, 1);

    Label lbValHex = new Label("计算结果(HEX)");
    txtValHex = new TextArea();
    txtValHex.setPrefRowCount(1);
    txtValHex.setWrapText(true);
    txtValHex.setEditable(false);

    Button btCopyMd5ValHex = new Button("复制");
    btCopyMd5ValHex.setOnAction((e) -> {
      ClipboardContent content = new ClipboardContent();
      content.putString(txtValHex.getText());
      Clipboard.getSystemClipboard().setContent(content);
      Toast.make("已复制").show(3000, win);
    });

    GridPane.setHalignment(lbValHex, HPos.LEFT);
    grid.add(lbValHex, 0, 2);

    GridPane.setHalignment(txtValHex, HPos.LEFT);
    grid.add(txtValHex, 1, 2);

    GridPane.setHalignment(btCopyMd5ValHex, HPos.LEFT);
    grid.add(btCopyMd5ValHex, 2, 2);

    Button btCalMd5 = new Button("计算MD5");
    btCalMd5.setOnAction((e) -> {
      clearResult();
      String origin = txtOrigin.getText();
      try {
        byte[] result = md5(origin);
        txtValB64.setText(toB64(result));
        txtValHex.setText(toHex(result));
      } catch (NoSuchAlgorithmException ex) {
        Toast.make("计算异常: " + ex.getMessage()).show(3000, win);
      }
    });

    GridPane.setHalignment(btCalMd5, HPos.CENTER);
    GridPane.setMargin(btCalMd5, new Insets(20, 0, 0, 0));
    grid.add(btCalMd5, 1, 3);

    Scene scene = new Scene(grid);
    scene.setFill(null);

    win.setScene(scene);
    win.setAlwaysOnTop(false);
  }

  protected void clearAll() {
    this.txtOrigin.clear();
    clearResult();
  }

  protected void clearResult() {
    this.txtValB64.clear();
    this.txtValHex.clear();
  }

  @Override
  public void open(MenuItem menuItem) throws UIException {
    if (win.isShowing()) {
      win.requestFocus();
    } else {
      win.show();
    }
  }

  @Override
  public void close() throws UIException {
    clearAll();
  }

  @Override
  public void detach() throws UIException {

  }

  @Override
  public String getId() {
    return "walawala.plugin.digest-calc";
  }

  @Override
  public String getName() {
    return "摘要计算器";
  }

  @Override
  public String[] getMenuPath() {
    return "加解密".split("/");
  }

  @Override
  public String getDescription() {
    return getName();
  }

  @Override
  public Image getIcon() {
    return null;
  }


  static byte[] md5(String origin) throws NoSuchAlgorithmException {
    MessageDigest md = MessageDigest.getInstance("MD5");
    md.update(origin.getBytes());
    return md.digest();
  }

  static String toB64(byte[] data) {
    return Base64.getEncoder().encodeToString(data);
  }

  static String toHex(byte[] data) {
    StringBuilder sb = new StringBuilder();
    for (int offset = 0; offset < data.length; offset++) {
      int val = data[offset];
      if (val < 0) {
        val += 256;
      } else if (val < 16) {
        sb.append(0);
      }
      sb.append(Integer.toHexString(val));
    }
    return sb.toString();
  }
}
